package main

import (
	"fmt"
	"unsafe"

	"github.com/apache/arrow/go/v6/arrow"
	"github.com/apache/arrow/go/v6/arrow/array"
	"github.com/apache/arrow/go/v6/arrow/memory"
)

// #cgo CXXFLAGS: -std=c++11
// #cgo CPPFLAGS: -I../../../../cc/src/include  -I/usr/include/c++/9
// #cgo LDFLAGS: -L../../../../build/lib -larrow_c
// #cgo LDFLAGS: -L/usr/local/lib -larrow -larrow_bundled_dependencies -larrow_dataset
// #cgo LDFLAGS: -lpthread -lstdc++
//
// #include <hello.h>
// #include <arrow_fill_c.h>
import "C"

const maxArrayLen = 1<<50 - 1

const nulls = 0
const withNulls = 0

func main() {
	fmt.Println("----------------------------------arrow cgo demo----------------------------------")

	C.SayHello(C.CString("lynnyuan"))
	sum := C.GoAddInt(C.int(1), C.int(4))
	fmt.Printf("sum: %d\n", sum)

	_sum := C.GoAddInts(C.int(1), C.int(3))
	fmt.Printf("sum: %d\n", _sum)

	int_array := C.GoFillInts(C.int(withNulls))

	len_null_bitmap := int64(int_array.len_null_bitmap)
	len_data := int64(int_array.len_data)
	rows := int(int_array.rows)
	_type := int(int_array._type)

	data_ptr := unsafe.Pointer(int_array.data)
	null_bitmap_ptr := unsafe.Pointer(int_array.null_bitmap)

	printCIntArray(len_null_bitmap, null_bitmap_ptr, len_data, data_ptr, rows, _type)

	NewGoIntArray(len_null_bitmap, null_bitmap_ptr, len_data, data_ptr, rows, _type)

	C.freeHolder()
	printCIntArray(len_null_bitmap, null_bitmap_ptr, len_data, data_ptr, rows, _type)

}

func printCIntArray(len_null_bitmap int64, null_bitmap_ptr unsafe.Pointer,
	len_data int64, data_ptr unsafe.Pointer, rows int, _type int) {
	data := (*[maxArrayLen]byte)(data_ptr)[:len_data:len_data]

	fmt.Println("-------------------------------------arrow go ----------------------------------------")
	{
		fmt.Printf("type=%d \t rows=%d \t len_null_bitmap=%d \t len_data=%d\n",
			_type, rows, len_null_bitmap, len_data)
		if len_null_bitmap > 0 {
			null_bitmap := (*[maxArrayLen]byte)(null_bitmap_ptr)[:len_null_bitmap:len_null_bitmap]

			fmt.Printf("null_bitmap\n\taddr %p, ptr:%p, type: %T, length:%d, val: %b\n %v\n",
				null_bitmap, null_bitmap_ptr, null_bitmap, len(null_bitmap), null_bitmap, null_bitmap)

		}

		fmt.Printf("data\n\taddr %p, ptr:%p, type: %T, length:%d,  val: %b\n %v\n",
			data, data_ptr, data, len(data), data, data)

	}
}

func NewGoIntArray(len_null_bitmap int64, null_bitmap_ptr unsafe.Pointer,
	len_data int64, data_ptr unsafe.Pointer, rows int, _type int) {
	data := (*[maxArrayLen]byte)(data_ptr)[:len_data:len_data]

	if rows == 0 {
		return
	}

	var null_bitmap = []byte{}
	if len_null_bitmap > 0 {
		null_bitmap = (*[maxArrayLen]byte)(null_bitmap_ptr)[:len_null_bitmap:len_null_bitmap]

		fmt.Printf("null_bitmap\n\taddr %p, ptr:%p, type: %T, length:%d, val: %b\n %v\n",
			null_bitmap, null_bitmap_ptr, null_bitmap, len(null_bitmap), null_bitmap, null_bitmap)

	}

	offset := 0

	data_buffer := memory.NewBufferBytes(data)
	null_bitmap_buffer := memory.NewBufferBytes(null_bitmap)
	buffers := []*memory.Buffer{null_bitmap_buffer, data_buffer}

	var arrow_type = arrow.PrimitiveTypes.Int8
	switch _type {
	case int(arrow.PrimitiveTypes.Int8.ID()):
		arrow_type = arrow.PrimitiveTypes.Int8
	case int(arrow.PrimitiveTypes.Int16.ID()):
		arrow_type = arrow.PrimitiveTypes.Int16
	case int(arrow.PrimitiveTypes.Int32.ID()):
		arrow_type = arrow.PrimitiveTypes.Int32
	case int(arrow.PrimitiveTypes.Int64.ID()):
		arrow_type = arrow.PrimitiveTypes.Int64
	default:
		fmt.Println("暂不支持的类型")
	}
	arrow_data := array.NewData(arrow_type, rows, buffers, nil, nulls, offset)

	int64_array := array.NewInt64Data(arrow_data)

	fmt.Printf("---------------------------Arrow Golang framework-------------------------------------\n")
	for _, val := range int64_array.Int64Values() {
		fmt.Printf("%d\t", val)
	}
	fmt.Println()
}
